﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.Reflection;
using DotaHelp.Models;
using System.Data.Objects;
using System.Web.Mvc;
using System.Text;
using System.Data.Common;

namespace DotaHelp.Helpers
{
    [AttributeUsage(AttributeTargets.Method)]
    public class SitemapAttribute : Attribute
    {
        public Type EntityTable { get; set; }
        public string DateField { get; set; }
        public bool IsPage { get; set; }
		public bool NotShowInSitemap { get; set; }

        public SitemapAttribute(Type entityTable, bool isPage)
        {
            this.EntityTable = entityTable;
            this.IsPage = isPage; 
        }

        public SitemapAttribute()
        {

        }

        public SitemapAttribute(Type entityTable)
        {
            this.EntityTable = entityTable;           
        }

        public SitemapAttribute(Type entityTable, string dateField)
        {
            this.EntityTable = entityTable;
            this.DateField = dateField;
        }

        public static IEnumerable<XElement> Load(UrlHelper url, Func<string, DateTime?, XElement> v)
        {
            var model = new DotaModel();

            foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
            {
                foreach (var method in type.GetMethods())
                {
                    var attr = (SitemapAttribute)method.GetCustomAttributes(typeof(SitemapAttribute), false).FirstOrDefault();
                    if (attr != null && !attr.NotShowInSitemap)
                    {
                        var controller = type.Name.Remove(type.Name.IndexOf("Controller"));

                        if (attr.EntityTable != null)
                        {
                            var table = model.MetadataWorkspace.GetEntityContainer("DotaModel", System.Data.Metadata.Edm.DataSpace.CSpace)
                                .BaseEntitySets.FirstOrDefault(f => f.ElementType.Name == attr.EntityTable.Name);

                            var hasIsDeleted = ((System.Data.Metadata.Edm.EntityType)(table.MetadataProperties["ElementType"].Value)).Properties.Contains("IsDeleted");

                            string queryString = string.Format(@"SELECT t.Id " + (!string.IsNullOrEmpty(attr.DateField)?", t." + attr.DateField:"") + " FROM DotaModel.{0} AS t " + (hasIsDeleted?"where t.isDeleted = false":""), table.Name);
                            var query = new ObjectQuery<DbDataRecord>(queryString, model);                            

                            if (attr.IsPage)
                            {
                                var count = query.Count() / 20;
                                for (var p = 1; p <= count; p++)
                                {
                                    yield return v(url.Action(method.Name, controller, new { page = p }, "http"), DateTime.Now); 
                                }
                            }
                            else
                            {
                                foreach (var row in query)
                                {
                                    yield return v(url.Action(method.Name, controller, new { id = (int)row["Id"] }, "http"), !string.IsNullOrEmpty(attr.DateField) ? (DateTime?)row[attr.DateField] : null);
                                }
                            }
                        }
                        else
                        {
                            yield return v(url.Action(method.Name, controller, null, "http"), DateTime.Now);
                        }
                    }
                }
            }
        }

        public static string Robots(UrlHelper url)
        {
            var list = new HashSet<string>();			         

            foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
            {
                foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                {
                    var attr = method.GetCustomAttributes(typeof(SitemapAttribute), false).Any();
                    var attr2 = method.GetCustomAttributes(typeof(System.Web.Mvc.ChildActionOnlyAttribute), false).Any();
                    if (!attr && !attr2 && type.Name.EndsWith("Controller") && !method.IsSpecialName)
                    {
                        var controller = type.Name.Remove(type.Name.IndexOf("Controller"));
                        list.Add("Disallow: " + url.Action(method.Name, controller, null));
                    }
                }
            }

            var result = new StringBuilder();

            result.AppendLine("Sitemap: http://dotahelp.ru/sitemap.xml");
			result.AppendLine("Host: dotahelp.ru");
            result.AppendLine();

            result.AppendLine("User-agent: *");
            foreach (var r in list) result.AppendLine(r);          

            return result.ToString();            
        }
    }
}